/*
* Copyright (C) Microsoft. All rights reserved.  
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not 
* use this file except in compliance with the License.  You may obtain a copy 
* of the License at http://www.apache.org/licenses/LICENSE-2.0  
* 
* THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
* WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
* MERCHANTABLITY OR NON-INFRINGEMENT. 
*
* See the Apache License, Version 2.0 for specific language governing 
* permissions and limitations under the License.
*
*/
#pragma once

#include <baja/common.hpp>
#include <baja/math.hpp>
#include <baja/graphics.hpp>
#include <baja/graphics/dx11.1/details/common.hpp>

namespace journal { namespace view {

namespace b = baja;
namespace g = baja::graphics;
namespace gd = baja::graphics::dx11_1::details;
namespace m = baja::math;

// our set of shaders for the journal is pre-canned and hardcoded here
enum class effect_id
{
	quad,
};

struct quad_constants
{
	b::float32 angle;
	m::point2d targetDimensions;
	m::point2d origin;
	b::float32 alpha;
};

struct ieffect_service : public b::ibase
{
    BAJA_INTERFACE(ieffect_service, "9688FAA0-3C4C-4A84-BCF5-EE71B2059E5B")

	virtual void setEffectConstants(const effect_id id, const void* buffer) = 0;
	virtual void setTexture(const std::shared_ptr<g::itexture>& texture) = 0;
	virtual void applyEffect(const effect_id id) = 0;
	virtual const void* getShaderBytes(const effect_id id) = 0;
	virtual const size_t getShaderSize(const effect_id id) = 0;
};

class effect_service : public ieffect_service
{
	struct effect_description
	{
		b::wchar* pixelShaderFile;
		b::wchar* vertexShaderFile;
		b::uint32 constantBufferSize;
	};

	struct effect
	{
		WRL::ComPtr<ID3D11PixelShader> pixelShader;
		WRL::ComPtr<ID3D11VertexShader> vertexShader;
		WRL::ComPtr<ID3D11Buffer> constantBuffer;
		std::vector<b::byte> vertexShaderBytes;
	};

	effect_service() {}

public:
    friend class std::_Ref_count_obj<effect_service>;
	static std::shared_ptr<effect_service> create()
	{
		std::shared_ptr<effect_service> returnValue = std::make_shared<effect_service>();
		returnValue->initialize();
		return returnValue;
	}

	// ieffect_service
	void setEffectConstants(const effect_id id, const void* buffer);
	void setTexture(const std::shared_ptr<g::itexture>& texture);
	void applyEffect(const effect_id id);
	const void* getShaderBytes(const effect_id id);
	const size_t getShaderSize(const effect_id id);

private:
	void initialize();
	void loadEffect(const effect_id eid, const effect_description& desc);

private:
	WRL::ComPtr<ID3D11DeviceContext> _d3d11DeviceContext;
	WRL::ComPtr<ID3D11Device> _d3d11Device;
	std::shared_ptr<g::iengine> _graphics;
	std::map<effect_id, effect> _map;
};

}} // namespace journal::view